// 本次线程池要设计成单例模式，单例模式是指在整个过程中，类只有一个对象
template <class T>
class ThreadPool;

#pragma once
#include <iostream>
#include <queue>  //用作 共享资源
#include <vector> //用作 存放线程们

#include <pthread.h>

#include "Threads.hpp"
#include "ProtectResourse.hpp"
#include "Log.hpp"

#define THREADSIZE 5 // 线程组中线程的个数

// 这里模版给的是共享资源的内容类型，可以派发内置类型，也可以派发自定义类型
template <class T>
class ThreadPool
{
private:
    // 构造函数要私有
    ThreadPool(int size = THREADSIZE)
        : _thread_size(size)
    {
        // 初始化线程组
        for (int i = 0; i < size; ++i)
        {
            _threads.emplace_back(
                std::bind(&ThreadPool<T>::Run,this));
        }

        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    ThreadPool(const ThreadPool<T> &threadpool) = delete;               // 禁拷贝构造
    ThreadPool<T> &operator=(const ThreadPool<T> &threadpool) = delete; // 禁赋值运算符重载

    //thread执行方法
    void *Run() // 重点！！！！！！！
    {
        T task;
        while (true)
        {
            {
                ProtectResourse protect(&_mutex);
                while (_shared_resourse.empty())
                {
                    Thread_Wait();
                }

                // 拿任务
                task = _shared_resourse.front();
                _shared_resourse.pop();
            }
            // 处理任务
            task._task(task._sk);
        }
        return nullptr;
    }

    // 唤醒一个线程 
    void One_Thread_Wakeup() {pthread_cond_signal(&_cond);}
    // 唤醒所有线程
    void All_Thread_Wakeup() {pthread_cond_broadcast(&_cond);}
    // 没有资源了，让线程组等待 
    void Thread_Wait() {pthread_cond_wait(&_cond, &_mutex);}

public:
    static ThreadPool<T> *GetOnce(int size = THREADSIZE)
    {
        //让认为_threadpool为空的线程进入，让其互斥，只允许一个线程创建单例
        //这里有个好处就是，认为不为空的线程，就直接返回这个线程池即可，减少竞争锁的线程数目，提高效率
        if (_threadpool == nullptr)
        {
            ProtectResourse protect(&_Once_mutex);
            if (_threadpool == nullptr) // 第一次创建
            {
                _threadpool = new ThreadPool<T>(size);
            }
        }
        return _threadpool;
    }
    // 析构函数【OK】
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    // 主线程派发任务【OK】
    void Push(const T& task)
    {
        ProtectResourse protect(&_mutex);
        {
            _shared_resourse.push(task);
            One_Thread_Wakeup();
        }
    }

    // 线程组执行任务
    void Start_Task() {for(auto &e : _threads){e.Start();}}
    // 分离线程组
    void Detach_Threads() {for(auto& e : _threads) {e.Detach();}}
    // 回收线程组
    void Join_Threads() {for (auto &e : _threads) {e.Join();}}

private:
    std::queue<T> _shared_resourse;            // 存放任务的共享资源
    int _thread_size;                          // 线程组中线程的个数
    std::vector<Thread<void*>> _threads; // 线程组
    pthread_mutex_t _mutex;                    // 线程组之间互斥访问共享资源的锁
    pthread_cond_t _cond;                      // 主线程与线程组之间要保持同步&&互斥时使用的条件变量

    static ThreadPool<T> *_threadpool;  // 指向单例对象
    static pthread_mutex_t _Once_mutex; // 防止多线程并发创建单例
};

template <class T>
ThreadPool<T>* ThreadPool<T>::_threadpool = nullptr;
template <class T>
pthread_mutex_t ThreadPool<T>::_Once_mutex = PTHREAD_MUTEX_INITIALIZER;